/* * * Copyright (c) 2014 CA. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * IN NO EVENT WILL CA BE LIABLE TO THE END USER OR ANY THIRD PARTY FOR ANY LOSS * OR DAMAGE, DIRECT OR INDIRECT, FROM THE USE OF THIS MATERIAL, * INCLUDING WITHOUT LIMITATION, LOST PROFITS, BUSINESS INTERRUPTION, GOODWILL, * OR LOST DATA, EVEN IF CA IS EXPRESSLY ADVISED OF SUCH LOSS OR DAMAGE. * */ package com.ca.apm.mongo.test; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.logging.Logger; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.CommandResult; import com.mongodb.DB; import com.mongodb.DBObject; // import com.mongodb.Mongo; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.ServerAddress; import de.flapdoodle.embed.mongo.MongodExecutable; import de.flapdoodle.embed.mongo.MongodProcess; import de.flapdoodle.embed.mongo.MongodStarter; import de.flapdoodle.embed.mongo.config.IMongodConfig; /** * Convenience class for setting up a MongoDB Replica set * */ public class MongoReplicaSetForTestFactory { private final static Logger logger = Logger.getLogger(MongoReplicaSetForTestFactory.class.getName()); public static final String ADMIN_DATABASE_NAME = "admin"; private final Map<String, List<IMongodConfig>> replicaSet; private final String database; private List<MongodProcess> mongodProcessList; public MongoReplicaSetForTestFactory( final Map<String, List<IMongodConfig>> replSet, final String dbName ) { this.replicaSet = replSet; this.database = dbName; } public void start() throws Throwable { this.mongodProcessList = new ArrayList<MongodProcess>(); Set<Entry<String, List<IMongodConfig>>> entries = replicaSet.entrySet(); for (Entry<String, List<IMongodConfig>> entry : entries) { initializeReplicaSet(entry); } } public void stop() { for (MongodProcess process : this.mongodProcessList) { process.stop(); } } private void initializeReplicaSet(Entry<String, List<IMongodConfig>> entry ) throws Exception { String replicaName = entry.getKey(); List<IMongodConfig> mongoConfigList = entry.getValue(); if (mongoConfigList.size() < 3) { throw new Exception( "A replica set must contain at least 3 members."); } // Create 3 mongod processes for (IMongodConfig mongoConfig : mongoConfigList) { if (!mongoConfig.replication().getReplSetName() .equals(replicaName)) { throw new Exception( "Replica set name must match in mongo configuration"); } MongodStarter starter = MongodStarter.getDefaultInstance(); MongodExecutable mongodExe = starter.prepare(mongoConfig); MongodProcess process = mongodExe.start(); mongodProcessList.add(process); } Thread.sleep(1000); MongoClientOptions mo = MongoClientOptions.builder() .autoConnectRetry(true) .build(); MongoClient mongo = new MongoClient(new ServerAddress(mongoConfigList.get(0).net() .getServerAddress().getHostName(), mongoConfigList.get(0) .net().getPort()), mo); DB mongoAdminDB = mongo.getDB(ADMIN_DATABASE_NAME); CommandResult cr = mongoAdminDB .command(new BasicDBObject("isMaster", 1)); logger.info("isMaster: " + cr); // Build BSON object replica set settings DBObject replicaSetSetting = new BasicDBObject(); replicaSetSetting.put("_id", replicaName); BasicDBList members = new BasicDBList(); int i = 0; for (IMongodConfig mongoConfig : mongoConfigList) { DBObject host = new BasicDBObject(); host.put("_id", i++); host.put("host", mongoConfig.net().getServerAddress().getHostName() + ":" + mongoConfig.net().getPort()); members.add(host); } replicaSetSetting.put("members", members); logger.info(replicaSetSetting.toString()); // Initialize replica set cr = mongoAdminDB.command(new BasicDBObject("replSetInitiate", replicaSetSetting)); logger.info("replSetInitiate: " + cr); Thread.sleep(5000); cr = mongoAdminDB.command(new BasicDBObject("replSetGetStatus", 1)); logger.info("replSetGetStatus: " + cr); // Check replica set status before to proceed while (!isReplicaSetStarted(cr)) { logger.info("Waiting for 3 seconds..."); Thread.sleep(1000); cr = mongoAdminDB.command(new BasicDBObject("replSetGetStatus", 1)); logger.info("replSetGetStatus: " + cr); } mongo.close(); mongo = null; } private boolean isReplicaSetStarted(BasicDBObject setting) { if (setting.get("members") == null) { return false; } BasicDBList members = (BasicDBList) setting.get("members"); for (Object m : members.toArray()) { BasicDBObject member = (BasicDBObject) m; logger.info(member.toString()); int state = member.getInt("state"); logger.info("state: " + state); // 1 - PRIMARY, 2 - SECONDARY, 7 - ARBITER if (state != 1 && state != 2 && state != 7) { return false; } } return true; } }